package schema

import (
	"lianzi_gos/internal/config"
	"strings"
	"time"

	"lianzi_gos/pkg/util"
)

// 业态表
type Business struct {
	ID          string      `json:"id" gorm:"size:20;primarykey;"`      // Unique ID
	Name        string      `json:"name" gorm:"size:32;index"`          // 业态名称
	Img         string      `json:"img" gorm:"size:200;index"`          // 业态图片
	Description string      `json:"description" gorm:"size:1024"`       // Details about dictionary
	Sequence    int         `json:"sequence" gorm:"index;"`             // Sequence for sorting
	Status      string      `json:"status" gorm:"size:20;index"`        // Status of dictionary (disabled, enabled)
	ParentID    string      `json:"parent_id" gorm:"size:20;index;"`    // Parent ID (From Business.ID)
	ParentPath  string      `json:"parent_path" gorm:"size:255;index;"` // Parent path (split by .)
	Children    *Businesses `json:"children" gorm:"-"`                  // Child nodes
	CreatedAt   time.Time   `json:"created_at" gorm:"index;"`           // Create time
	UpdatedAt   time.Time   `json:"updated_at" gorm:"index;"`           // Update time
}

func (a *Business) TableName() string {
	return config.C.FormatTableName("business")
}

// Defining the query parameters for the `Business` struct.
type BusinessQueryParam struct {
	util.PaginationParam
	LikeName         string `form:"name"` // Display name of menu
	Status           string `form:"-"`    // Status of dictionary (disabled, enabled)
	ParentID         string `form:"-"`    // Parent ID (From Business.ID)
	ParentPathPrefix string `form:"-"`    // Parent path (split by .)
}

// Defining the query options for the `Business` struct.
type BusinessQueryOptions struct {
	util.QueryOptions
}

// Defining the query result for the `Business` struct.
type BusinessQueryResult struct {
	Data       Businesses
	PageResult *util.PaginationResult
}

// Defining the slice of `Business` struct.
type Businesses []*Business

func (a Businesses) Len() int {
	return len(a)
}

func (a Businesses) Less(i, j int) bool {
	if a[i].Sequence == a[j].Sequence {
		return a[i].CreatedAt.Unix() > a[j].CreatedAt.Unix()
	}
	return a[i].Sequence > a[j].Sequence
}

func (a Businesses) Swap(i, j int) {
	a[i], a[j] = a[j], a[i]
}
func (a Businesses) ToMap() map[string]*Business {
	m := make(map[string]*Business)
	for _, item := range a {
		m[item.ID] = item
	}
	return m
}

func (a Businesses) SplitParentIDs() []string {
	parentIDs := make([]string, 0, len(a))
	idMapper := make(map[string]struct{})
	for _, item := range a {
		if _, ok := idMapper[item.ID]; ok {
			continue
		}
		idMapper[item.ID] = struct{}{}
		if pp := item.ParentPath; pp != "" {
			for _, pid := range strings.Split(pp, util.TreePathDelimiter) {
				if pid == "" {
					continue
				}
				if _, ok := idMapper[pid]; ok {
					continue
				}
				parentIDs = append(parentIDs, pid)
				idMapper[pid] = struct{}{}
			}
		}
	}
	return parentIDs
}

func (a Businesses) ToTree() Businesses {
	var list Businesses
	m := a.ToMap()
	for _, item := range a {
		if item.ParentPath == "" {
			list = append(list, item)
			continue
		}
		if parent, ok := m[item.ParentPath]; ok {
			if parent.Children == nil {
				children := Businesses{item}
				parent.Children = &children
				continue
			}
			*parent.Children = append(*parent.Children, item)
		}
	}
	return list
}

// Defining the data structure for creating a `Business` struct.
type BusinessForm struct {
	Name        string `json:"name" binding:"required,max=32"`                   // 业态名称
	Img         string `json:"img"`                                              // Details about dictionary
	Description string `json:"description"`                                      // Details about dictionary
	Sequence    int    `json:"sequence"`                                         // Sequence for sorting
	Status      string `json:"status" binding:"required,oneof=disabled enabled"` // Status of dictionary (disabled, enabled)
	ParentID    string `json:"parent_id"`                                        // Parent ID (From Business.ID)
}

// A validation function for the `BusinessForm` struct.
func (a *BusinessForm) Validate() error {
	return nil
}

// Convert `BusinessForm` to `Business` object.
func (a *BusinessForm) FillTo(business *Business) error {
	business.Name = a.Name
	business.Img = a.Img
	business.Description = a.Description
	business.Sequence = a.Sequence
	business.Status = a.Status
	business.ParentID = a.ParentID
	return nil
}
